import { animation, AnimationClip, Sprite, SpriteFrame } from 'cc'
import ResourceMgr from '../runtime/ResourceMgr'
import { StateMachine } from './StateMachine'
import { sortSpriteFrame } from '../utils'

export const iframeTime = 1 / 8 // 一秒8帧

interface IAniFrameEvent {
  /** 事件触发的时间点，单位为秒 */
  frame: number
  /** 表示事件触发时回调的函数名称，会去当前节点绑定的所有事件中寻找 */
  func: string
  /** 回调函数的参数 */
  params: any[]
}

export class State {
  private fsm: StateMachine // 状态机
  private path: string // 资源路径
  private wrapMode: AnimationClip.WrapMode // 动画循环模式
  animationClip: AnimationClip
  speed: number // 动画播放速度
  events: IAniFrameEvent[] = [] // 动画帧事件

  constructor(
    fsm: StateMachine,
    path: string,
    wrapMode = AnimationClip.WrapMode.Normal,
    speed = iframeTime,
    events: IAniFrameEvent[] = [],
  ) {
    this.fsm = fsm
    this.path = path
    this.wrapMode = wrapMode
    this.speed = speed
    this.events = events
    this.init()
  }

  async init() {
    // 加载精灵帧资源
    const promise = ResourceMgr.Instance.loadSpriteFrame(this.path)
    this.fsm.watingState.push(promise) // 将当前异步任务推到列表中,在PlayerStateMachine中使用promise.all统一执行

    const spriteFrames = await promise
    // console.log('spriteFrames', spriteFrames)
    // 创建动画
    this.animationClip = new AnimationClip()
    this.animationClip.name = this.path // 设置动画名称
    const track = new animation.ObjectTrack() // 创建一个对象轨道
    track.path = new animation.TrackPath().toComponent(Sprite).toProperty('spriteFrame') // 指定对象路径，即指定目标对象为Sprite节点的 "spriteFrame" 属性
    const frames: Array<[number, SpriteFrame]> = sortSpriteFrame(spriteFrames).map((item, index) => [
      this.speed * index,
      item,
    ]) // 获取所有关键帧
    // track.channel.curve.assignSorted([
    //   // 为通道的曲线添加关键帧
    //   [0.4, { value: 0.4 }], // 添加一个关键帧 元素1：时间  元素2：变幻的属性
    //   [0.6, { value: 0.6 }],
    //   [0.8, { value: 0.8 }],
    // ])

    this.animationClip.duration = frames.length * iframeTime // 整个动画剪辑的周期 = 关键帧数 * 每一帧的时长
    track.channel.curve.assignSorted(frames) // 为通道的曲线添加关键帧
    this.animationClip.addTrack(track) // 最后将轨道添加到动画剪辑以应用
    this.animationClip.wrapMode = this.wrapMode // 循环播放

    // 添加动画帧事件
    for (let i = 0; i < this.events.length; i++) {
      this.animationClip.events.push(this.events[i])
    }
    this.animationClip.updateEventDatas()
  }

  run() {
    // 如果当前动画等于将要播放的动画，那么不切换
    if (this.fsm.animationComponent.defaultClip?.name === this.animationClip.name) return

    this.fsm.animationComponent.defaultClip = this.animationClip // 添加默认动画剪辑
    this.fsm.animationComponent.play() // 播放
  }
}
